package com.huaxin.common.Deprecated;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.util.ArrayMap;

import java.lang.ref.WeakReference;

/**
 * Created by hebing on 2016/4/6.
 * Notice: you must use this class to create a intent
 */
public class MapCenter {

    /**************************************自定义注入***************************************/
    /**
     * 无缝注入任何公共库界面的任何方法
     */
    private static ArrayMap<Class, BaseInject.SimpleInject> injectMap;

    static void map(Class clazz, BaseInject.SimpleInject inject) {
        if (inject == null) return;
        if (injectMap == null) injectMap = new ArrayMap<>();
        injectMap.put(clazz, inject);
    }

    static BaseInject.SimpleInject getInject(Class clazz) {
        if (injectMap == null || !injectMap.containsKey(clazz)) return null;
        return injectMap.get(clazz);
    }

    /**************************************界面 注入相关，实现灵活可控的界面***************************************/
    /**
     * 注入接口
     */
    interface ViewBuilder {

        void onBind(BaseImp base);

        /**
         * 返回一个布局ID，正常情况下为0，如果你想完全的替换应用的界面，重写它即可
         *
         * @return 布局ID
         */
        int generatorViewId();

        /**
         * 界面元素的构建,比如：
         * 1 添加模型元素
         * 2 隐藏某些元素
         */
        void onBuild();

        void onResume();

        void onPause();

        void onSaveInstanceState(Bundle outState);

        void onRestoreInstanceState(Bundle savedInstanceState);

        void unBind();
    }

    // a smaple class
    public static class SampleViewBuilder implements ViewBuilder {

        protected WeakReference<BaseImp> mBase;
        protected ViewBuilder childBuilder;

        @Override
        public void onBind(BaseImp base) {
            mBase = new WeakReference<>(base);
            childBuilder = MapCenter.getBuild(getClass());
            if (childBuilder != null) childBuilder.onBind(base);

        }

        @Override
        public int generatorViewId() {
            if (childBuilder != null) return childBuilder.generatorViewId();
            return 0;
        }

        public void onBuild() {
            if (childBuilder != null) childBuilder.onBuild();
        }

        @Override
        public void onResume() {
            if (childBuilder != null) childBuilder.onResume();
        }

        @Override
        public void onPause() {
            if (childBuilder != null) childBuilder.onPause();
        }

        public void onSaveInstanceState(Bundle outState) {
            if (childBuilder != null) childBuilder.onSaveInstanceState(outState);
        }

        public void onRestoreInstanceState(Bundle savedInstanceState) {
            if (childBuilder != null) childBuilder.onRestoreInstanceState(savedInstanceState);
        }

        @Override
        public void unBind() {
            if (childBuilder != null) childBuilder.unBind();
            if (mBase != null) mBase.clear();
            mBase = null;
            childBuilder = null;
        }

        /**
         * return the instance of baseImp,maybe return null
         *
         * @return maybe return null
         */
        protected BaseImp getBase() {
            if (mBase != null) return mBase.get();
            return null;
        }
    }

    private static ArrayMap<Class, ViewBuilder> buildMap;

    /**
     * 注入界面
     *
     * @param clazz   注入（界面）的class（可以为activity/fragment/ViewBuilder）
     * @param builder 界面构造器
     */
    public static void map(Class clazz, SampleViewBuilder builder) {
        //lazy init
        if (buildMap == null) buildMap = new ArrayMap<>();
        buildMap.put(clazz, builder);
    }

    static ViewBuilder getBuild(Class clazz) {
        if (buildMap == null || !buildMap.containsKey(clazz)) return null;
        return buildMap.get(clazz);
    }
    /**************************************Intent 映射相关，实现灵活可控的跳转***************************************/
    /**
     * 类映射集合<br>
     * 比如你想修改common模块默认跳转可以设定与默认的类映射关系
     */
    private static ArrayMap<Class, Class> clsMap;
    private static ArrayMap<Class, Bundle> extraMap;

    /**
     * 映射新的跳转入口到common中
     *
     * @param defaultClazz 默认的common跳转入口
     * @param yourClazz    产品模块的跳转入口
     */
    static void map(Class defaultClazz, Class yourClazz) {
        map(defaultClazz, yourClazz, null);
    }

    /**
     * 映射新的跳转入口到common中
     *
     * @param defaultClazz 默认的common跳转入口
     * @param yourClazz    产品模块的跳转入口
     * @param extra        intent附带的参数
     */
    static void map(Class defaultClazz, Class yourClazz, Bundle extra) {
        // lazy init it
        if (clsMap == null) clsMap = new ArrayMap<>();
        clsMap.put(defaultClazz, yourClazz);
        if (extra != null) {
            if (extraMap == null) extraMap = new ArrayMap<>();
            extraMap.put(yourClazz, extra);
        }
    }

    static Intent filterIntent(Context context, Intent intent) {
        ComponentName componentName = intent.getComponent();
        if (componentName != null) {
            try {
                Class clazz = Class.forName(componentName.getClassName());
                final Class bind = getBindClass(clazz);
                final Bundle bundle = getBindBundle(bind);
                if (clazz != bind) {
                    intent.setClass(context, bind);
                }
                if (bundle != null)
                    intent.putExtras(bundle);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
        return intent;
    }

    static Intent getIntent(String action) {
        Intent intent = new Intent(action);
        return intent;
    }

    static Intent getIntent(Context context, Class clazz) {
        return getIntent(context, clazz, true);
    }

    /**
     * @param context current context
     * @param clazz   to start
     * @param allowed if true,will to find the map class from cache
     * @return a intent
     */
    static Intent getIntent(Context context, Class clazz, boolean allowed) {
        final Intent intent;
        if (allowed) {
            final Class bind = getBindClass(clazz);
            final Bundle bundle = getBindBundle(bind);
            intent = new Intent(context, bind);
            if (bundle != null)
                intent.putExtras(bundle);
        } else {
            intent = new Intent(context, clazz);
        }
        return intent;
    }

    /**
     * maybe A class Map to B class And B class Map to C class. so we should find the final Map class of A
     *
     * @param clazz to find
     * @return return the final bind class
     */
    private static Class getBindClass(Class clazz) {
        if (clsMap == null) return clazz;

        Class find = clazz;
        while (clsMap.get(find) != null) {
            find = clsMap.get(find);
        }
        return find;
    }

    private static Bundle getBindBundle(Class clazz) {
        if (extraMap == null || !clsMap.containsKey(clazz)) return null;
        return extraMap.get(clazz);
    }

}
